using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using WPCoco.Tilesets;
using Microsoft.Xna.Framework.Graphics;

namespace WPCoco.Specialized
{
    public class TileLayer : AffineNode
    {
        public TileLayer()
        {
            sample = new SamplerState();
            sample.Filter = TextureFilter.Point;
        }

        SamplerState sample;

        void Recreate(int width, int height) 
        {
            map = new int[height, width];
        }

        void UpdateSize() 
        {
            Width = size.Width * tileSize.X;
            Height = size.Height * tileSize.Y;
        }

        Size size;

        public Size Size
        {
            get { return size; }
            set 
            {
                if (size == value) return;
                size = value;
                Recreate(size.Width, size.Height);
                UpdateSize();
            }
        }

        Tileset tileset;

        public Tileset Tileset
        {
            get { return tileset; }
            set { tileset = value; }
        }

        int[,] map;

        public int this[int row, int column]
        {
            get { return map[row, column]; }
            set { map[row, column] = value; }
        }

        Vector2 tileSize = new Vector2(1, 1);

        public Vector2 TileSize
        {
            get { return tileSize; }
            set 
            { 
                tileSize = value;
                UpdateSize();
            }
        }

        public override void SelfDraw(GameTime gameTime)
        {
            if (tileset == null) return;
            
            Matrix inv = Matrix.Invert(WorldMatrix.Shared.CurrentMatrix);

            int f0, f1, c0, c1;

            Vector2 v0 = Vector2.Transform(new Vector2(0, 0), inv);
            Vector2 v1 = Vector2.Transform(new Vector2(0, Screen.Height), inv);
            Vector2 v2 = Vector2.Transform(new Vector2(Screen.Width, 0), inv);
            Vector2 v3 = Vector2.Transform(new Vector2(Screen.Width, Screen.Height), inv);

            f0 = (int)(Math.Min(Math.Min(Math.Min(v0.Y, v1.Y), v2.Y), v3.Y) / tileSize.Y);
            f1 = (int)(Math.Max(Math.Max(Math.Max(v0.Y, v1.Y), v2.Y), v3.Y) / tileSize.Y);
            c0 = (int)(Math.Min(Math.Min(Math.Min(v0.X, v1.X), v2.X), v3.X) / tileSize.X);
            c1 = (int)(Math.Max(Math.Max(Math.Max(v0.X, v1.X), v2.X), v3.X) / tileSize.X);

            if (f0 < 0) f0 = 0; if (f0 >= size.Height) f0 = size.Height - 1;
            if (f1 < 0) f1 = 0; if (f1 >= size.Height) f1 = size.Height - 1;
            if (c0 < 0) c0 = 0; if (c0 >= size.Width) c0 = size.Width - 1;
            if (c1 < 0) c1 = 0; if (c1 >= size.Width) c1 = size.Width - 1;

            CachedSpriteBatch spriteBatch = SpriteBatchCache.GetVolatile();

            spriteBatch.Begin(SpriteSortMode.Texture, null, sample, null, null, null, WorldMatrix.Shared.CurrentMatrix);

            int index = -1, last;
            float x = c0 * tileSize.X, y = f0 * tileSize.Y;
            TextureFrame frame = new TextureFrame();
            for (int i = f0; i <= f1; i++, y += tileSize.Y)
            {
                for (int j = c0; j <= c1; j++, x += tileSize.X)
                {
                    last = index;
                    index = map[i, j];
                    if (index != last)
                        frame = tileset[index];
                    spriteBatch.Draw(frame.Texture, new Vector2(x + frame.TextureTrim.Left, y + frame.TextureTrim.Top), frame.TextureRegion, Color.White);
                    //
                }
                x = c0 * tileSize.X;
            }
            var gd = Coco.Shared.GraphicsDevice;

            spriteBatch.End();

        }
    }
}
